#include "KitharaUser.h"
#include "Universal/Universal.h"
#include <QtConcurrent>
#include <windows.h>
#include "Assemblies/Base/AppData.h"

KitharaUser::KitharaUser(QObject *parent) : QObject(parent)
{
    /*  打开驱动  */
    if (const KSError error = KS_openDriver(customer_number_); error != KS_OK)
    {
        Universal::OutputErr(error, "KS_openDriver", "Unable to open the driver!");
        return;
    }
}

KitharaUser::~KitharaUser()
{
    /* 关闭驱动 */
    if (const KSError error = KS_closeDriver(); error != KS_OK)
    {
        Universal::OutputErr(error, "KS_closeDriver", "Unable to close the driver!");
    }
    Sleep(3000);
};

bool KitharaUser::Init()
{
    /* 创建共享内存 */
    KSError error = KS_createSharedMemEx(&shared_mem_handle_, "", sizeof(SharedData),KSF_NO_FLAGS);
    if (error != KS_OK)
    {
        Universal::OutputErr(error, "KS_createSharedMemEx", "Unable to create the shared memory!");
        return false;
    }

    /* 获取共享内存句柄，并于用户层数据绑定 */
    error = KS_getSharedMemEx(shared_mem_handle_, reinterpret_cast<void **>(&user_data_), KSF_NO_FLAGS);
    if (error != KS_OK)
    {
        Universal::OutputErr(error, "KS_getSharedMemEx", "Unable to get the shared memory!");
        return false;
    }

    /* 加载内核层DLl */
    error = KS_loadKernel(&user_data_->kernel_handle, "KernelUDP.dll", nullptr, nullptr,KSF_KERNEL_EXEC | KSF_SAVE_FPU);
    if (error != KS_OK)
    {
        Universal::OutputErr(error, "KS_loadKernel", "Unable to load the kernel!");
        return false;
    }

    return true;
}

bool KitharaUser::Start()
{
    /* 遍历网卡 */
    /* 获取网卡名称
     *
     * KSF_ACTIVE： 该设备不仅在Windows 系统中可用，而且还与 Kithara 驱动程序永久连接。
     *
     */
    KSError error = KS_enumDevices("NET", network_index_, user_data_->device_name, KSF_NO_FLAGS);
    if (error != KS_OK)
    {
        Universal::OutputErr(error, "KS_enumDevices", "Unable to query network device name!");
        return false;
    }

    // 为了发送 IP 数据包，我们必须设置自己的 IP 地址和子网掩码。
    // 注意：以太网帧中的数据必须是“大端”！

    byte b3{},b2{},b1{},b0{};
    QStringList local_ip = AppData::Instance()->GetLocalIp().split(".");
    for (int i = 0; i < local_ip.size(); ++i)
    {
        // qDebug() << i  << " -- "  << local_ip[i].toUInt();
        if (i == 0)
        {
            b3 = local_ip[i].toUInt();
        }

        if (i == 1)
        {
            b2 = local_ip[i].toUInt();
        }

        if (i == 2)
        {
            b1 = local_ip[i].toUInt();
        }

        if (i == 3)
        {
            b0 = local_ip[i].toUInt();
        }
    }

    KS_makeIPv4(&user_data_->ip_config.localAddress, b3, b2, b1, b0);
    KS_makeIPv4(&user_data_->ip_config.subnetMask, 255, 255, 255, 0);

    QStringList remote_ip = AppData::Instance()->GetRemoteIp().split(".");
    for (int i = 0; i < remote_ip.size(); ++i)
    {
        // qDebug() << i  << " -- "  << remote_ip[i].toUInt();
        if (i == 0)
        {
            b3 = remote_ip[i].toUInt();
        }

        if (i == 1)
        {
            b2 = remote_ip[i].toUInt();
        }

        if (i == 2)
        {
            b1 = remote_ip[i].toUInt();
        }

        if (i == 3)
        {
            b0 = remote_ip[i].toUInt();
        }
    }

    KS_makeIPv4(&user_data_->ip_config.gatewayAddress,  b3, b2, b1, 1);
    KS_makeIPv4(&user_data_->remote_addr,  b3, b2, b1, b0);
    user_data_->port_config = AppData::Instance()->GetPort();

    error = KS_execKernelFunctionEx(user_data_->kernel_handle, "InitKernel", shared_mem_handle_, KS_INVALID_HANDLE, KSF_NO_FLAGS);
    if (error != KS_OK)
    {
        Universal::OutputErr(error, "KS_execKernelFunctionEx", "Unable to initialize the kernel DLL!");
        return false;
    }

    // 创建定时器的回调函数
    error = KS_createKernelCallBack(&timer_call_back_handle_, user_data_->kernel_handle, "SendBufferContent", nullptr, KSF_DIRECT_EXEC | KSF_SAVE_FPU, 0); // Priority
    if (error != KS_OK)
    {
        return error;
    }

    error = KS_createTimer(&timer_handle_, 1000 * 10 * 1000, timer_call_back_handle_, KSF_DIRECT_EXEC); // 100ms
    if (error != KS_OK)
    {
        return error;
    }

    /* 创建线程 */
    future_ = QtConcurrent::run(&KitharaUser::RecevicePipeData,this);
    return true;
}

QStringList KitharaUser::GetNetworkList() const
{
    QStringList network_list;
    for (int i = 0;; ++i)
    {
        char device_name[256];
        if (const KSError error = KS_enumDevices("NET", i, device_name, KSF_NO_FLAGS); error != KS_OK)
        {
            if (KSERROR_CODE(error) != KSERROR_DEVICE_NOT_FOUND)
            {
                Universal::OutputErr(error, "KS_enumDevices", "Unable to query network device name!");
            }
            if (KSERROR_CODE(error) == KSERROR_DEVICE_NOT_FOUND && !i)
            {
                Universal::OutputTxt("No network adapters found");
                return {};
            }

            break;
        }
        network_list.append(device_name);
    }

    return network_list;
}

void KitharaUser::SetNetworkIndex(const int index)
{
    if (index < 0)
    {
        return;
    }

    network_index_ = index;
}

void KitharaUser::WaitForStop()
{
    while (true)
    {
        if (user_data_->is_finished == 1)
       {
            return;
        }

        if(!SendUdpData("Hello KRTS"))
        {
            Universal::OutputErr(KS_OK, "SendUdpData", "Unable to send data!");
        }

        Sleep(100);
    }
}

void KitharaUser::Stop() const
{
    if (user_data_ != nullptr)
    {
        user_data_->is_finished = 1;
    }
}

void KitharaUser::UnInit()
{
    if (timer_handle_ != NULL)
    {
        KS_stopTimer(timer_handle_);
        KS_removeTimer(timer_handle_);
        timer_handle_ = NULL;
    }

    // 删除回调
    if (timer_call_back_handle_ != NULL)
    {
        KS_removeCallBack(timer_call_back_handle_);
        timer_call_back_handle_ = NULL;
    }

    // 等待线程退出
    future_.waitForFinished();

    KSError error;
    /* 卸载内核层DLL */
    if (shared_mem_handle_ != NULL && user_data_->kernel_handle != NULL)
    {
        if (error = KS_execKernelFunctionEx(user_data_->kernel_handle, "ExitKernel", KS_INVALID_HANDLE, KS_INVALID_HANDLE, KSF_NO_FLAGS)
            ; error != KS_OK)
        {
            Universal::OutputErr(error, "KS_execKernelFunctionEx", "Error while deallocating resources on kernel level!");
        }

        error = KS_freeKernel(user_data_->kernel_handle);
        if (error != KS_OK)
        {
            Universal::OutputErr(error, "KS_freeKernel", "Unable to unload the kernel!");
        }
    }

    /* 释放共享内存 */
    if (shared_mem_handle_ != NULL)
    {
        error = KS_freeSharedMemEx(shared_mem_handle_, KSF_NO_FLAGS);
        if (error != KS_OK)
        {
            Universal::OutputErr(error, "KS_freeSharedMemEx", "Unable to free the shared memory!");
        }
        else
        {
            user_data_ = nullptr;
        }
    }
}

void KitharaUser::RecevicePipeData()
{
    KSError error = KS_OK;
    char read_buffer[BUFFER_SIZE];
    int length;

    while (true)
    {
        if (user_data_->is_finished != 0)
        {
            break;
        }

        error = KS_waitForEvent(user_data_->receive_event_handle, KSF_NO_FLAGS, 5 * MS);
        if (error != KS_OK) { continue; }

        while (KS_OK == KS_getPipe(user_data_->pipe_handle, read_buffer, BUFFER_SIZE, &length, KSF_NO_FLAGS))
        {
            read_buffer[length] = '\0';
            Universal::OutputTxt(read_buffer, false);
            if (auto str = QString(read_buffer); !str.isEmpty())
            {
                emit SendData(str);

                // 接收后回复
                // if(!SendUdpData("Hello KRTS"))
                // {
                //    Universal::OutputErr(KS_OK, "SendUdpData", "Unable to send data!");
                // }

                //if ( user_data_->jitter_data.count % 10 == 0)
                // {
                //     const JitterTestData data = user_data_->jitter_data;
                //     QString jitter_str = "最大抖动：" + QString::number(data.max_value*1.0/US,'f',2) + "us  最小抖动:" + QString::number(data.min_value*1.0/US,'f',2) + "us \n";
                //     for (int i = 0; i < 10; i++)
                //     {
                //         if (i>8)
                //         {
                //             jitter_str +=  QString::number(i+1) + "us以外的个数：" + QString::number(data.classes[i]) + " 占比：" + QString::number(data.classes[i]*100.00 / data.count,'f',2) + "%" + "\n";
                //         }
                //         else
                //         {
                //             jitter_str += QString::number(i)+ " - " + QString::number(i+1) + "之间的抖动：" + QString::number(data.classes[i]) + " 占比：" + QString::number(data.classes[i]*100.00 / data.count,'f',2) + "%" + "\n";
                //         }
                //     }
                //
                //     emit SendData(jitter_str);
                // }
            }
        }
    }

    Universal::OutputTxt("Receiving thread has been finished.");
}

bool KitharaUser::SendUdpData(const QString &message)
{
    if (user_data_ == nullptr)
    {
        return false;
    }

    strcpy_s(user_data_->send_buffer, message.toStdString().c_str());
    user_data_->send_length = (int)message.length();
    // if (const KSError error = KS_execKernelFunctionEx(user_data_->kernel_handle, "SendBufferContent", KS_INVALID_HANDLE, KS_INVALID_HANDLE, KSF_NO_FLAGS); error != KS_OK)
    // {
    //     Universal::OutputErr(error, "SendBufferContent", "Error while sending!");
    //     return false;
    // }
    //
    // emit SendData(message);

    return true;
}